home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / lddemon.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  7KB  |  284 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: lddemon.c,v 1.5 1996/09/12 14:53:20 digulla Exp $
  4.     $Log: lddemon.c,v $
  5.     Revision 1.5  1996/09/12 14:53:20  digulla
  6.     The loader code should use symbolic names
  7.  
  8.     Revision 1.4  1996/09/11 13:00:16  digulla
  9.     Use correct alignment (M. Fleischer)
  10.  
  11.     Revision 1.3  1996/08/13 13:52:48  digulla
  12.     Replaced <dos/dosextens.h> by "dos_intern.h" or added "dos_intern.h"
  13.     Replaced __AROS_LA by __AROS_LHA
  14.  
  15.     Revision 1.2  1996/08/01 17:40:53  digulla
  16.     Added standard header for all files
  17.  
  18.     Desc:
  19.     Lang: english
  20. */
  21. #include <exec/execbase.h>
  22. #include <exec/resident.h>
  23. #include <exec/memory.h>
  24. #include <exec/errors.h>
  25. #include <clib/exec_protos.h>
  26. #include <dos/dosextens.h>
  27. #include <clib/dos_protos.h>
  28. #include "dos_intern.h"
  29.  
  30. #define ALLOCVEC_TOTAL \
  31. (DOUBLEALIGN>sizeof(ULONG)?DOUBLEALIGN:sizeof(ULONG))
  32.  
  33. static BPTR LDLoad(STRPTR name, STRPTR basedir, struct DosLibrary *DOSBase)
  34. {
  35.     BPTR seglist;
  36.     struct Process *me=(struct Process *)FindTask(NULL);
  37.     struct DosList *dl1, *dl2;
  38.     struct Process *caller=DOSBase->dl_LDCaller;
  39.  
  40.     if(caller->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  41.     {
  42.     /* Try the caller's current dir */
  43.     me->pr_CurrentDir=caller->pr_CurrentDir;
  44.     seglist=LoadSeg(name);
  45.     if(seglist)
  46.         return seglist;
  47.     }
  48.     /* Try the system's default directory. */
  49.     dl1=LockDosList(LDF_ALL|LDF_READ);
  50.     dl2=FindDosEntry(dl1,basedir,LDF_VOLUMES);
  51.     if(dl2==NULL)
  52.     dl2=FindDosEntry(dl1,basedir,LDF_DEVICES|LDF_ASSIGNS);
  53.     if(dl2!=NULL)
  54.     {
  55.     struct FileHandle fh;
  56.     fh.fh_Unit  =dl2->dol_Unit;
  57.     fh.fh_Device=dl2->dol_Device;
  58.     me->pr_CurrentDir=MKBADDR(&fh);
  59.     seglist=LoadSeg(name);
  60.     }
  61.     UnLockDosList(LDF_ALL|LDF_READ);
  62.     return seglist;
  63. }
  64.  
  65. static struct Library *LDInit(BPTR seglist, struct DosLibrary *DOSBase)
  66. {
  67.     BPTR seg=seglist;
  68.     while(seg)
  69.     {
  70.     STRPTR addr=(STRPTR)BADDR(seg)-ALLOCVEC_TOTAL;
  71.     ULONG size=*(ULONG *)addr;
  72.     for(;size>=sizeof(struct Resident);size-=PTRALIGN,addr+=PTRALIGN)
  73.     {
  74.         struct Resident *res=(struct Resident *)addr;
  75.         if(res->rt_MatchWord==RTC_MATCHWORD&&res->rt_MatchTag==res)
  76.         {
  77.         struct Library *lib=InitResident(res,seglist);
  78.         if(lib==NULL)
  79.             UnLoadSeg(seglist);
  80.         return lib;
  81.         }
  82.     }
  83.     seg=*(BPTR *)BADDR(seg);
  84.     }
  85.     UnLoadSeg(seglist);
  86.     return NULL;
  87. }
  88.  
  89. void LDDemon(void)
  90. {
  91.     extern struct DosLibrary *DOSBase;
  92.     BPTR seglist;
  93.     for(;;)
  94.     {
  95.     Wait(SIGF_DOS);
  96.     seglist=LDLoad(DOSBase->dl_LDName,(STRPTR)DOSBase->dl_LDPtr,DOSBase);
  97.     DOSBase->dl_LDPtr=LDInit(seglist,DOSBase);
  98.     Signal(&DOSBase->dl_LDCaller->pr_Task,SIGF_DOS);
  99.     }
  100. }
  101.  
  102. __AROS_LH2(struct Library *,OpenLibrary,
  103. __AROS_LHA(STRPTR,libName,A1),__AROS_LHA(ULONG,version,D0),
  104. struct ExecBase *,sysbase,0,Dos)
  105. {
  106.     __AROS_FUNC_INIT
  107.     extern struct DosLibrary *DOSBase;
  108.     struct Library *library;
  109.     Forbid();
  110.     library=(struct Library *)FindName(&SysBase->LibList,libName);
  111.     if(library==NULL)
  112.     {
  113.     ObtainSemaphore(&DOSBase->dl_LDSigSem);
  114.     DOSBase->dl_LDCaller=(struct Process *)FindTask(NULL);
  115.     DOSBase->dl_LDName  =libName;
  116.     DOSBase->dl_LDPtr   ="libs:";
  117.     Signal((struct Task *)DOSBase->dl_LDDemon,SIGF_DOS);
  118.     Wait(SIGF_DOS);
  119.     library=(struct Library *)DOSBase->dl_LDPtr;
  120.     ReleaseSemaphore(&DOSBase->dl_LDSigSem);
  121.     if(library!=NULL)
  122.         AddLibrary(library);
  123.     }
  124.     if(library!=NULL)
  125.     {
  126.     if(library->lib_Version>=version)
  127.         library=__AROS_LVO_CALL1(struct Library *,1,library,version,d0);
  128.     else
  129.         library=NULL;
  130.     }
  131.     Permit();
  132.     return library;
  133.     __AROS_FUNC_EXIT
  134. }
  135.  
  136. __AROS_LH4(BYTE,OpenDevice,
  137. __AROS_LHA(STRPTR,devName,A0),__AROS_LHA(ULONG,unitNumber,D0),
  138. __AROS_LHA(struct IORequest *,iORequest,A1),__AROS_LHA(ULONG,flags,D1),
  139. struct ExecBase *,sysbase,0,Dos)
  140. {
  141.     __AROS_FUNC_INIT
  142.     extern struct DosLibrary *DOSBase;
  143.     struct Device *device;
  144.     UBYTE ret=IOERR_OPENFAIL;
  145.     Forbid();
  146.     device=(struct Device *)FindName(&SysBase->DeviceList,devName);
  147.     if(device==NULL)
  148.     {
  149.     ObtainSemaphore(&DOSBase->dl_LDSigSem);
  150.     DOSBase->dl_LDCaller=(struct Process *)FindTask(NULL);
  151.     DOSBase->dl_LDName  =devName;
  152.     DOSBase->dl_LDPtr   ="devs:";
  153.     Signal((struct Task *)DOSBase->dl_LDDemon,SIGF_DOS);
  154.     Wait(SIGF_DOS);
  155.     device=(struct Device *)DOSBase->dl_LDPtr;
  156.     ReleaseSemaphore(&DOSBase->dl_LDSigSem);
  157.     if(device!=NULL)
  158.         AddDevice(device);
  159.     }
  160.     if(device!=NULL)
  161.     {
  162.     iORequest->io_Error=0;
  163.     iORequest->io_Device=device;
  164.     iORequest->io_Flags=flags;
  165.     iORequest->io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  166.     __AROS_LVO_CALL3(void,1,device,iORequest,A1,unitNumber,D0,flags,D1);
  167.     ret=iORequest->io_Error;
  168.     if(ret)
  169.         iORequest->io_Device=NULL;
  170.     }
  171.     Permit();
  172.     return ret;
  173.     __AROS_FUNC_EXIT
  174. }
  175.  
  176. __AROS_LH1(void,CloseLibrary,
  177. __AROS_LHA(struct Library *,library,A1),
  178. struct ExecBase *,sysbase,0,Dos)
  179. {
  180.     __AROS_FUNC_INIT
  181.     extern struct DosLibrary *DOSBase;
  182.     BPTR seglist;
  183.     if(library!=NULL)
  184.     {
  185.     Forbid();
  186.     seglist=__AROS_LVO_CALL0(BPTR,2,library);
  187.     if(seglist)
  188.     {
  189.         DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  190.         UnLoadSeg(seglist);
  191.     }
  192.     Permit();
  193.     }
  194.     __AROS_FUNC_EXIT
  195. }
  196.  
  197. __AROS_LH1(void,CloseDevice,
  198. __AROS_LHA(struct IORequest *,iORequest,A1),
  199. struct ExecBase *,sysbase,0,Dos)
  200. {
  201.     __AROS_FUNC_INIT
  202.     extern struct DosLibrary *DOSBase;
  203.     BPTR seglist;
  204.     Forbid();
  205.     if(iORequest->io_Device!=NULL)
  206.     {
  207.     seglist=__AROS_LVO_CALL1(BPTR,2,iORequest->io_Device,iORequest,A1);
  208.     iORequest->io_Device=(struct Device *)-1;
  209.     if(seglist)
  210.     {
  211.         DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  212.         UnLoadSeg(seglist);
  213.     }
  214.     }
  215.     Permit();
  216.     __AROS_FUNC_EXIT
  217. }
  218.  
  219. __AROS_LH1(void,RemLibrary,
  220. __AROS_LHA(struct Library *,library,A1),
  221. struct ExecBase *,sysbase,0,Dos)
  222. {
  223.     __AROS_FUNC_INIT
  224.     extern struct DosLibrary *DOSBase;
  225.     BPTR seglist;
  226.     Forbid();
  227.     seglist=__AROS_LVO_CALL0(BPTR,3,library);
  228.     if(seglist)
  229.     {
  230.     DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  231.     UnLoadSeg(seglist);
  232.     }
  233.     Permit();
  234.     __AROS_FUNC_EXIT
  235. }
  236.  
  237. LONG LDFlush(void)
  238. {
  239.     extern struct DosLibrary *DOSBase;
  240.     struct Library *library;
  241.  
  242.     DOSBase->dl_LDReturn=MEM_DID_NOTHING;
  243.  
  244.     /* Forbid() is already done, but I don't want to rely on it. */
  245.     Forbid();
  246.  
  247.     /* Follow the linked list of shared libraries. */
  248.     library=(struct Library *)SysBase->LibList.lh_Head;
  249.     while(library->lib_Node.ln_Succ!=NULL)
  250.     {
  251.     /* Flush libraries with a 0 open count */
  252.     if(!library->lib_OpenCnt)
  253.     {
  254.         RemLibrary(library);
  255.         /* Did it really go away? */
  256.         if(DOSBase->dl_LDReturn!=MEM_DID_NOTHING)
  257.         {
  258.         /* Yes. Return it. */
  259.         Permit();
  260.         return DOSBase->dl_LDReturn;
  261.         }
  262.     }
  263.     /* Go to next. */
  264.     library=(struct Library *)library->lib_Node.ln_Succ;
  265.     }
  266.     /* Do the same with the device list. */
  267.     library=(struct Library *)SysBase->DeviceList.lh_Head;
  268.     while(library->lib_Node.ln_Succ!=NULL)
  269.     {
  270.     if(!library->lib_OpenCnt)
  271.     {
  272.         RemLibrary(library);
  273.         if(DOSBase->dl_LDReturn!=MEM_DID_NOTHING)
  274.         {
  275.         Permit();
  276.         return DOSBase->dl_LDReturn;
  277.         }
  278.     }
  279.     library=(struct Library *)library->lib_Node.ln_Succ;
  280.     }
  281.     Permit();
  282.     return MEM_DID_NOTHING;
  283. }
  284.